package sample.mybatis.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.dt.activity.center.binding.ActivityHotUpdateBinding;
import com.dt.activity.center.binding.model.ActivityHotUpdateMessage;
import com.dt.activity.center.bo.ActivityExpandContentBO;
import com.dt.activity.center.bo.activity.*;
import com.dt.activity.center.bo.bizcontent.BizContentRelationBO;
import com.dt.activity.center.bo.material.MaterialResourceFileBO;
import com.dt.activity.center.bo.template.TemplateBO;
import com.dt.activity.center.bo.template.TemplateConfigBOEx;
import com.dt.activity.center.bo.topic.TopicReplyBO;
import com.dt.activity.center.bo.user.ActivityPresenterBO;
import com.dt.activity.center.config.RedisKeyConfig;
import com.dt.activity.center.constant.Constant;
import com.dt.activity.center.dto.activity.*;
import com.dt.activity.center.dto.bizcontent.BizContentRelationQueryContentDTO;
import com.dt.activity.center.dto.bizcontent.BizContentRelationSaveDTO;
import com.dt.activity.center.dto.material.ActivityResultRoleDTO;
import com.dt.activity.center.dto.template.TemplateQueryDTO;
import com.dt.activity.center.dto.theme.plan.PlanPageDTO;
import com.dt.activity.center.dto.user.UserJoinActivityCheckDTO;
import com.dt.activity.center.enums.*;
import com.dt.activity.center.facade.activity.ActivityConverter;
import com.dt.activity.center.facade.bizcontent.BizContentRelationConverter;
import com.dt.activity.center.facade.user.ActivityPresenterConverter;
import com.dt.activity.center.feign.client.NationalPlanFeignClient;
import com.dt.activity.center.feign.client.OrgFeignClient;
import com.dt.activity.center.feign.client.TopicFeignClient;
import com.dt.activity.center.feign.client.dto.InstitutionTopicBO;
import com.dt.activity.center.feign.client.dto.national.TrainPlanBO;
import com.dt.activity.center.feign.client.dto.user.CoopGroupDTO;
import com.dt.activity.center.feign.server.dto.*;
import com.dt.activity.center.feign.server.vo.ActivityCountQueryFeignVO;
import com.dt.activity.center.mapper.*;
import com.dt.activity.center.service.activity.ActivityConfigReader;
import com.dt.activity.center.service.activity.ActivityPushReader;
import com.dt.activity.center.service.activity.ActivityReader;
import com.dt.activity.center.service.activity.UserJoinActivityChecker;
import com.dt.activity.center.model.*;
import com.dt.activity.center.service.activity.*;
import com.dt.activity.center.service.biz.DoubleTeacherActivityFiller;
import com.dt.activity.center.service.bizcontent.BizContentRelationReader;
import com.dt.activity.center.service.material.MaterialResourceReader;
import com.dt.activity.center.service.statistics.StatisticsReader;
import com.dt.activity.center.service.template.SceneConfigReader;
import com.dt.activity.center.service.template.TemplateConfigReader;
import com.dt.activity.center.service.template.TemplateReader;
import com.dt.activity.center.service.user.ActivityPresenterReader;
import com.dt.activity.center.service.tool.ToolReader;
import com.dt.activity.center.service.user.ActivityUserReader;
import com.dt.activity.center.service.user.impl.ActivityUserAuditReaderImpl;
import com.dt.activity.center.utils.RedisUtil;
import com.dt.activity.center.web.model.theme.teachplan.PlanOperatePageVO;
import com.dt.activity.center.web.model.theme.teachplan.PlanPageVO;
import com.dt.activity.center.web.model.activity.statistics.ActivityStatisticsDTO;
import com.dt.activity.center.web.model.activity.*;
import com.dt.framework.business.constant.BusinessCode;
import com.dt.framework.business.util.StringUtil;
import com.dt.framework.core.exception.BusinessException;
import com.dt.framework.core.mvc.Pagination;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 活动表 (Activity)表服务实现类
 *
 * @author zhangzy
 * @since 2021-06-24 12:20:16
 */
@Service("activityReader")
@Slf4j
public class ActivityReaderImpl implements ActivityReader {

    @Resource
    private ActivityDOMapper activityMapper;
    @Resource
    private ActivityExpandDOMapper ActivityExpandDOMapper;
    @Resource
    private ActivityConverter activityConverter;
    @Resource
    private ActivityUserDOMapper activityUserDOMapper;
    @Resource
    private BizContentRelationConverter bizContentRelationConverter;
    @Resource
    private ThemeDOMapper themeDOMapper;
    @Resource
    private ActivityConfigReader activityConfigReader;
    @Resource
    private BizContentRelationReader bizContentRelationReader;
    @Resource
    private ActivityUserReader activityUserReader;
    @Resource
    private ActivityUserAuditReaderImpl activityUserAuditReader;
    @Resource
    private StatisticsReader statisticsReader;
    @Resource
    private MaterialResourceReader materialResourceReader;
    @Resource
    private MaterialResourceDOMapper materialResourceDOMapper;

    @Resource
    private ActivityHotUpdateBinding activityHotUpdateBinding;

    @Resource
    private UserJoinActivityChecker userJoinActivityChecker;
    @Resource
    private DoubleTeacherActivityFiller doubleTeacherActivityFiller;
    @Resource
    private TemplateReader templateReader;
    @Resource
    private TemplateConfigReader templateConfigReader;

    @Resource
    private ActivityPushReader activityPushReader;
    @Resource
    private SceneConfigReader sceneConfigReader;

    @Resource
    private ToolReader toolReader;

    @Resource
    private ActivityPresenterReader activityPresenterReader;

    @Resource
    private ActivityPresenterConverter activityPresenterConverter;

    @Resource
    private ActivityExpandContentReader activityExpandContentReader;

    @Resource
    private OrgFeignClient orgFeignClient;

    @Resource
    private NationalPlanFeignClient nationalPlanFeignClient;
    @Resource
    private TopicFeignClient topicFeignClient;

    @Resource
    private RedisUtil redisUtil;

    private final static String ALL_STAGE_SUBJECT = "9999";

    @Override
    public ActivityBO selectByActivityId(Long activityId) {
        ActivityDO activityDO = activityMapper.selectActivityById(activityId);
        if (activityDO == null) {
            throw new BusinessException(BusinessCode.ACTIVITY_NOT_FOUND_CODE, BusinessCode.ACTIVITY_NOT_FOUND_MESSAGE);
        }
        ActivityBO activityBO = activityConverter.convertToBO(activityDO);
        ActivityExpandDO activityExpandDO = ActivityExpandDOMapper.selectByActivityId(activityDO.getId());
        activityConverter.fillActivityExpand(activityBO, activityExpandDO);
        return activityBO;
    }

    @Override
    public ActivityBO selectActivityDetail(ActivityDetailDTO activityDetailDTO) {
        // 先从redis中查询ActivityBO，其中包含activity实体信息、activityExpand、activityConfig、活动成果数
        ActivityBO activityBO = this.getActivityBOFromRedis(activityDetailDTO);

        // 活动人物
        this.fillActivityPerson(activityDetailDTO, activityBO);

        // 活动扩展数据
        this.fillActivityExpandContent(activityBO);
        /**
         * 教研主题
         */
        List<ActivityExpandContentBO> expandContentList = activityBO.getExpandContentList();
        String researchTheme = this.getResearchTheme(expandContentList);
        activityBO.setResearchTheme(researchTheme);
        // bizContentRelation
        BizContentRelationQueryContentDTO bizContentRelationQueryContentDTO = BizContentRelationQueryContentDTO
                .builder()
                .contentId(activityBO.getId())
                .contentType(BizContentType.ACTIVITY.getType())
                .build();
        List<BizContentRelationBO> bizContentRelationBOS = bizContentRelationReader
                .selectSaveDTOByContent(bizContentRelationQueryContentDTO);
        List<BizContentRelationSaveDTO> bizContentRelationSaveDTOList = bizContentRelationConverter
                .convertBOToSaveDTOlist(bizContentRelationBOS);
        activityBO.setBizList(bizContentRelationSaveDTOList);

        // 该用户是否参加 参与度
        this.fillJoinState(activityDetailDTO, activityBO);

        // 距离开始活动还有多久
        this.fillHowLongStart(activityBO);

        // 活动场景信息
        this.fillScene(activityBO);

        this.fillSourse(activityBO);

        // 被推送次数
        SearchActivityPushDTO searchActivityPushDTO = SearchActivityPushDTO.builder()
                .sourceActivityId(activityBO.getId())
                .invalid(InvalidEnum.NORMAL.getCode())
                .build();
        List<ActivityPushBO> activityPushBOList = activityPushReader.getActivityPushByCondition(searchActivityPushDTO);
        activityBO.setPushTimes(activityPushBOList.size());

        ActivityHotUpdateMessage activityHotUpdateMessage = ActivityHotUpdateMessage.builder()
                .activityId(activityBO.getId())
                .viewCount(1)
                .build();
        this.activityHotUpdateBinding.output().send(MessageBuilder.withPayload(activityHotUpdateMessage)
                .build());

        return activityBO;
    }

    private void fillSourse(ActivityBO activityBO) {
        SceneEnum sceneEnum = SceneEnum.getEnum(activityBO.getBizType());

        switch (sceneEnum.getSource()) {
            case joint: {
                final List<InstitutionTopicBO> topicList = topicFeignClient.getTopicByBiz(activityBO.getId(),
                        "activity");
                if (!CollectionUtils.isEmpty(topicList)) {
                    List<SourceDTO> list = topicList.stream().map(e -> SourceDTO.builder()
                            .bizId(e.getId())
                            .bizTitle(e.getTitle())
                            .bizType("topic")
                            .build()).collect(Collectors.toList());
                    activityBO.setSourceList(list);
                    break;
                }

            }
            case course: {
                break;
            }
        }
    }

    private void fillScene(ActivityBO activityBO) {
        // sceneInfoVO.setScene(activityBO.getBizType());
        activityBO.setSceneBasicName(sceneConfigReader.getSceneBasicName(activityBO.getBizType()));
    }

    private void fillActivityExpandContent(ActivityBO activityBO) {
        List<ActivityExpandContentBO> result = activityExpandContentReader
                .getActivityExpandContentByActivityId(activityBO.getId());
        activityBO.setExpandContentList(result);
    }

    /**
     * 获取活动人物相关数据
     * 
     * @param activityDetailDTO
     * @param activityBO
     */
    private void fillActivityPerson(ActivityDetailDTO activityDetailDTO, ActivityBO activityBO) {
        SceneEnum sceneEnum = SceneEnum.getEnum(activityBO.getBizType());
        if (!sceneEnum.equals(SceneEnum.XXZX)) {
            return;
        }
        // 先从缓存中查询
        String key = StringUtil.format(RedisKeyConfig.ACTIVITY_PERSON_KEY, activityDetailDTO.getActivityId());
        String content = redisUtil.get(key);
        ActivityPersonCacheDTO activityPersonCacheDTO = JSON.parseObject(content, ActivityPersonCacheDTO.class);
        if (Objects.nonNull(activityPersonCacheDTO)) {
            // 主备人
            activityBO.setActivityPrincipals(activityPersonCacheDTO.getPrincipals());
            // 授课教师
            activityBO.setActivityTeachers(activityPersonCacheDTO.getTeachers());
            // 专家
            activityBO.setActivityExperts(activityPersonCacheDTO.getExperts());
        } else {
            List<ActivityPresenterBO> activityPresenterBOS = activityPresenterReader
                    .getActivityPresenterByActivityId(activityDetailDTO.getActivityId());
            // 主备人
            List<ActivityPresenterBO> principals = activityPresenterBOS.stream()
                    .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                            && ActivityPresenterPersonTypeEnum.PRINCIPAL.getCode().equals(item.getPersonType()))
                    .collect(Collectors.toList());
            // 属性转换
            List<ActivityPrincipalDTO> principalDTOS = activityPresenterConverter.convertToPrincipalDTOS(principals);
            activityBO.setActivityPrincipals(principalDTOS);
            // 授课教师
            List<ActivityPresenterBO> teachers = activityPresenterBOS.stream()
                    .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                            && ActivityPresenterPersonTypeEnum.TEACHER.getCode().equals(item.getPersonType()))
                    .collect(Collectors.toList());
            // 属性转换
            List<ActivityTeacherDTO> teacherDTOS = activityPresenterConverter.convertToTeacherDTOS(teachers);
            activityBO.setActivityTeachers(teacherDTOS);
            // 专家
            List<ActivityPresenterBO> experts = activityPresenterBOS.stream()
                    .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                            && ActivityPresenterPersonTypeEnum.EXPERT.getCode().equals(item.getPersonType()))
                    .collect(Collectors.toList());
            // 属性转换
            List<ActivityExpertDTO> expertDTOS = activityPresenterConverter.convertToExpertDTOS(experts);
            activityBO.setActivityExperts(expertDTOS);
            // 加入缓存
            ActivityPersonCacheDTO cacheDTO = ActivityPersonCacheDTO.builder()
                    .principals(principalDTOS)
                    .teachers(teacherDTOS)
                    .experts(expertDTOS)
                    .build();
            // 缓存 60s
            redisUtil.set(key, JSON.toJSONString(cacheDTO), 60);
        }
    }

    /**
     * 获取活动详情
     * 
     * @param activityDetailDTO
     * @return
     */
    @Override
    public ActivityBO getActivityBOFromRedis(ActivityDetailDTO activityDetailDTO) {
        ActivityBO activityBO;
        String key = StringUtil.format(RedisKeyConfig.ACTIVITY_DETAIL_KEY, activityDetailDTO.getActivityId());
        String content = redisUtil.get(key);
        if (StringUtils.isNotBlank(content)) {
            activityBO = JSON.parseObject(content, ActivityBO.class);
        } else {
            ActivityDO activityDO = activityMapper.selectActivityDetail(activityDetailDTO);
            if (activityDO == null) {
                throw new BusinessException(BusinessCode.ACTIVITY_NOT_FOUND_CODE,
                        BusinessCode.ACTIVITY_NOT_FOUND_MESSAGE);
            }
            activityBO = activityConverter.convertToBO(activityDO);
            // 填充activityExpand
            ActivityExpandDO activityExpandDO = ActivityExpandDOMapper.selectByActivityId(activityDO.getId());
            activityConverter.fillActivityExpand(activityBO, activityExpandDO);

            // config
            Map<String, String> configMap = activityConfigReader.getConfigMap(activityDO.getId(),
                    ActivityConfigSourceTypeEnum.ACTIVITY.name());
            activityBO.setConfig(configMap);

            // 活动成果数 改变活动成果的地方无需删除缓存，可以存在延迟性
            this.fillAchievementCount(activityBO);

            // 缓存redis 1分钟
            redisUtil.set(key, JSON.toJSONString(activityBO), 60);
        }
        return activityBO;
    }

    private void fillAchievementCount(ActivityBO activityBO) {
        ActivityResultRoleDTO activityResultRoleDTO = new ActivityResultRoleDTO();
        activityResultRoleDTO.setActivityId(activityBO.getId());
        Integer count = materialResourceReader.getActivityResultCountByRoleKeyList(activityResultRoleDTO);
        activityBO.setAchievementCount(count);
    }

    private void fillHowLongStart(ActivityBO activityBO) {
        if (ActivityStateEnum.WITH_START.getCode().equals(activityBO.getState())) {
            Long startTime = activityBO.getStartTime().getTime();
            Long nowTime = new Date().getTime();
            activityBO.setHowLongStart(startTime - nowTime);
        }
    }

    private void fillJoinState(ActivityDetailDTO activityDetailDTO, ActivityBO activityBO) {
        Long userId = activityDetailDTO.getUserId();
        // 0未参与 1已参与 2审核中
        ActivityJoinStateEnum joinState;
        if (userId != null) {
            boolean existUser = activityUserReader.existByActivityIdAndUserId(activityBO.getId(), userId);
            if (existUser) {
                // 用户已参加
                joinState = ActivityJoinStateEnum.JOINED;
                // 获取用户平均完成率
                BigDecimal completeRate = statisticsReader.queryActivityUserComplete(activityBO.getId(), userId)
                        .getCompleteRate();
                activityBO.setScore(completeRate.multiply(new BigDecimal(100)).intValue());
                // 获取用户参与率
            } else {
                // 未参加，判断是否审批中
                boolean existUserAudit = activityUserAuditReader.existByActivityIdAndUserId(activityBO.getId(), userId,
                        AuditStatusEnum.AUDITING);
                if (existUserAudit) {
                    joinState = ActivityJoinStateEnum.AUDITING;
                } else {
                    // 用户未参加 是否在参加范围内
                    UserJoinActivityCheckDTO userJoinActivityCheckDTO = UserJoinActivityCheckDTO.builder()
                            .activityId(activityBO.getId())
                            .bizType(SceneEnum.getEnum(activityBO.getBizType()))
                            .userId(activityDetailDTO.getUserId())
                            .bizId2(activityDetailDTO.getBizId2())
                            .build();
                    ActivityJoinCheckDTO inScope = userJoinActivityChecker
                            .userJoinActivityCheck(userJoinActivityCheckDTO);
                    if (inScope.getAllowJoin()) {
                        joinState = ActivityJoinStateEnum.UN_JOIN;
                        activityBO.setCanJoinOrgList(inScope.getOrgList());
                    } else {
                        joinState = ActivityJoinStateEnum.NOT_IN_SCOPE;
                    }
                }
            }
        } else {
            joinState = ActivityJoinStateEnum.UN_JOIN;
        }
        activityBO.setJoinState(joinState.getCode());
    }

    @Override
    public Pagination<ActivityPageBO> page(ActivityPageDTO activityPageDTO) {
        if (ALL_STAGE_SUBJECT.equals(activityPageDTO.getStageId())) {
            activityPageDTO.setStageId(null);
        }
        if (ALL_STAGE_SUBJECT.equals(activityPageDTO.getSubjectId())) {
            activityPageDTO.setSubjectId(null);
        }
        /**
         * 如果是双师/入校中台 用户端
         */
        if (!CollectionUtils.isEmpty(activityPageDTO.getBizTypeList()) &&
                (activityPageDTO.getBizTypeList().contains(SceneEnum.DOUBLETEACHER.getType()) ||
                        activityPageDTO.getBizTypeList().contains(SceneEnum.SCHOOL_WAND.getType()))) {
            doubleTeacherActivityFiller.fillDoubleTeacherActivityPage(activityPageDTO);
        }
        Pagination<ActivityPageBO> page = new Pagination<>(activityPageDTO.getPageIndex(),
                activityPageDTO.getPageSize());
        Integer count = activityMapper.countByActivityPageDTO(activityPageDTO);
        if (count < 1) {
            page.setTotal(0);
            page.setRows(Lists.newArrayList());
            return page;
        }

        List<ActivityPageDO> list = activityMapper.selectActivityPageByActivityPageDTO(activityPageDTO);

        List<ActivityPageBO> result = activityConverter.convertPageDOToBOList(list);
        this.fillScore(result);

        page.setTotal(count);
        page.setRows(result);
        return page;
    }

    @Override
    public Integer getTemplateCodeByActivityId(Long activityId) {
        String key = StringUtil.format(RedisKeyConfig.ACTIVITY_TEMPLATE_CODE, activityId);
        String templateCodeStr = redisUtil.get(key);
        if (StringUtils.isNotEmpty(templateCodeStr)) {
            return Integer.parseInt(templateCodeStr);
        }
        Integer templateCode = activityMapper.getTemplateCodeByActivityId(activityId);
        redisUtil.set(key, templateCode.toString(), RedisKeyConfig.ACTIVITY_TEMPLATE_CODE_INVALID_TIME);
        return templateCode;
    }

    @Override
    public List<ActivityPageBO> listByActivityIds(List<Long> ids) {

        List<ActivityPageDO> list = activityMapper.listByActivityIds(ids);

        return activityConverter.convertPageDOToBOList(list);
    }

    @Override
    public List<String> userTypeTags(Long userId) {
        String redisKey = StringUtil.format(RedisKeyConfig.USER_ACTIVITY_TYPES_KEY, userId);
        String s = redisUtil.get(redisKey);
        if (StringUtils.isBlank(s)) {
            return Lists.newArrayList();
        }
        return JSON.parseArray(s, String.class);
    }

    @Override
    public ActivityCountBO myCount(ActivityMyCountQueryDTO activityMyCountQueryDTO) {
        return activityMapper.myCount(activityMyCountQueryDTO);
    }

    @Override
    public Pagination<ActivityManagementListVO> operatePlanAllPage(ActivityPageDTO dto) {
        try {
            Pagination<ActivityManagementListVO> page;
            if (Objects.isNull(dto)) {
                page = new Pagination<>(1, 20);
                page.setTotal(0);
                page.setRows(Lists.newArrayList());
                return page;
            }
            changeParameters(dto);
            page = new Pagination<>(dto.getPageIndex(), dto.getPageSize());
            Integer count = activityMapper.planPageCount(dto);
            if (count < 1) {
                page.setTotal(0);
                page.setRows(Lists.newArrayList());
                return page;
            }
            List<ActivityPlanPageBO> list = activityMapper.planPage(dto);

            page.setTotal(count);
            List<ActivityManagementListVO> result = new ArrayList<>();
            list.forEach(o -> {
                result.add(ActivityManagementListVO.builder()
                        .activityId(o.getActivityId())
                        .title(o.getTitle())
                        .activityType(o.getActivityType())
                        .subjectStage(o.getSubjectStage())
                        .creatorName(o.getCreatorName())
                        .creatorId(o.getCreatorId().toString())
                        .activityCode(o.getActivityCode())
                        .account(!StringUtils.isEmpty(o.getAccount())
                                && Constant.TEL_LENGTH.equals(o.getAccount().length())
                                && o.getAccount().matches("[0-9]+")
                                        ? o.getAccount().substring(0, 3) + "****" + o.getAccount().substring(7)
                                        : o.getAccount())
                        .createTime(o.getCreateTime())
                        .state(o.getState())
                        .memberCount(o.getMemberCount())
                        .top(o.getTop())
                        .publish(o.getShowScope())
                        .dtBrand(o.getDtBrand())
                        .dtTenant(o.getDtTenant())
                        .build());
            });
            page.setRows(result);
            return page;
        } catch (Exception e) {
            log.error("ActivityReaderImpl.operateAllPage={}", e.getMessage());
            return new Pagination<>(1, 20);
        }
    }

    @Override
    public Pagination<ActivityPlanListVO> onlinePlanPage(ActivityPageDTO dto) {
        String key = StringUtil.format(RedisKeyConfig.PLAN_ACTIVITY_INDEX_PAGE_KEY, dto.toString());
        String json = redisUtil.get(key);
        if (StringUtils.isNotBlank(json)) {
            log.info("ActivityReaderImpl#onlinePlanPage,redis取出缓存数据:{}", json);
            Pagination<ActivityPlanListVO> result = JSON.parseObject(json,
                    new TypeReference<Pagination<ActivityPlanListVO>>() {
                    });
            return result;
        } else {
            Pagination<ActivityPlanListVO> page = this.getOnlinePlanPageData(dto);
            log.info("ActivityReaderImpl#onlinePlanPage,redis放入缓存数据key:{}", key);
            redisUtil.set(key, JSON.toJSONString(page), RedisKeyConfig.PLAN_ACTIVITY_INDEX_PAGE_INVALID_TIME);
            return page;
        }

    }

    // public static void main(String[] args) {
    // ActivityPageDTO activityPageDTO = ActivityPageDTO
    // .builder()
    // .stageId("1222")
    // .pageIndex(1)
    // .pageSize(16)
    // .build();
    // System.out.println("对象:"+activityPageDTO);
    // }

    private Pagination<ActivityPlanListVO> getOnlinePlanPageData(ActivityPageDTO dto) {
        Pagination<ActivityPlanListVO> page;
        if (Objects.isNull(dto)) {
            page = new Pagination<>(1, 20);
            page.setTotal(0);
            page.setRows(Lists.newArrayList());
            return page;
        }
        changeParameters(dto);
        page = new Pagination<>(dto.getPageIndex(), dto.getPageSize());
        Integer count = activityMapper.planPageCount(dto);
        if (count < 1) {
            page.setTotal(0);
            page.setRows(Lists.newArrayList());
            return page;
        }
        List<ActivityPlanPageBO> list = activityMapper.planPage(dto);
        // 修改角色
        roleKey(list, dto.getUserId());
        page.setTotal(count);
        List<ActivityPlanListVO> result = new ArrayList<>();
        list.forEach(o -> {
            result.add(ActivityPlanListVO.builder()
                    .activityId(o.getActivityId())
                    .title(o.getTitle())
                    .top(o.getTop())
                    .state(o.getState())
                    .memberCount(o.getMemberCount())
                    .structure(o.getStructure())
                    .roleKey(o.getRoleKey())
                    .structureAvatar(o.getStructureAvatar())
                    .activityCover(o.getActivityCover())
                    .startTime(o.getStartTime())
                    .showScope(o.getShowScope())
                    .build());
        });
        page.setRows(result);
        return page;
    }

    @Override
    public TemplateThemeAndOrgVO themeAndOrg(String scene) {
        String key = StringUtil.format(RedisKeyConfig.THEME_AND_ORG_KEY, scene);
        String json = redisUtil.get(key);
        if (StringUtils.isNotBlank(json)) {
            log.info("ActivityReaderImpl#themeAndOrg,redis取出缓存数据:{}", json);
            return JSON.parseObject(json, TemplateThemeAndOrgVO.class);
        } else {
            TemplateThemeAndOrgVO templateThemeAndOrgVO = new TemplateThemeAndOrgVO();
            TemplateQueryDTO templateQueryDTO = TemplateQueryDTO.builder()
                    .scene(scene)
                    .build();
            List<TemplateBO> templateByQueryDTO = templateReader.getTemplateByQueryDTO(templateQueryDTO);
            if (!CollectionUtils.isEmpty(templateByQueryDTO)) {
                TemplateBO templateBO = templateByQueryDTO.get(0);
                Long templateId = templateBO.getId();

                TemplateConfigBOEx themeConfig = templateConfigReader.getTemplateFunctionInfoByKey(templateId, null,
                        ConfigKeyEnum.PROPERTY_ACTIVITY_THEME.getConfigKey());
                if (themeConfig != null && StringUtils.isNotBlank(themeConfig.getFunctionValue())) {
                    String value = themeConfig.getFunctionValue();
                    templateThemeAndOrgVO.setTheme(value);
                }

                TemplateConfigBOEx orgConfig = templateConfigReader.getTemplateFunctionInfoByKey(templateId, null,
                        ConfigKeyEnum.PROPERTY_ACTIVITY_ORGANIZATION.getConfigKey());
                if (orgConfig != null && StringUtils.isNotBlank(orgConfig.getFunctionValue())) {
                    String value = orgConfig.getFunctionValue();
                    templateThemeAndOrgVO.setOrg(value);
                }
            }
            redisUtil.set(key, JSON.toJSONString(templateThemeAndOrgVO), RedisKeyConfig.THEME_AND_ORG_INVALID_TIME);
            log.info("ActivityReaderImpl#themeAndOrg,取出数据库数据:{}", JSON.toJSONString(templateThemeAndOrgVO));
            return templateThemeAndOrgVO;
        }
    }

    @Override
    public Pagination<ActivityBaseListVO> basePage(ActivityPageDTO dto) {
        try {
            Pagination<ActivityBaseListVO> page;
            if (Objects.isNull(dto)) {
                page = new Pagination<>(1, 20);
                page.setTotal(0);
                page.setRows(Lists.newArrayList());
                return page;
            }

            page = new Pagination<>(dto.getPageIndex(), dto.getPageSize());
            Integer count = activityMapper.planPageCount(dto);
            if (count < 1) {
                page.setTotal(0);
                page.setRows(Lists.newArrayList());
                return page;
            }
            List<ActivityPlanPageBO> list = activityMapper.planPage(dto);
            // 修改角色
            roleKey(list, dto.getUserId());
            page.setTotal(count);
            List<ActivityBaseListVO> result = new ArrayList<>();
            list.forEach(o -> {
                result.add(ActivityBaseListVO.builder()
                        .activityId(o.getActivityId())
                        .title(o.getTitle())
                        .memberCount(o.getMemberCount())
                        .state(o.getState())
                        .activityCover(o.getActivityCover())
                        .startTime(o.getStartTime())
                        .roleKey(o.getRoleKey())
                        .creatorId(o.getCreatorId())
                        .creatorName(o.getCreatorName())
                        .creatorAvatar(o.getCreatorAvatar())
                        .build());
            });
            page.setRows(result);
            return page;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("ActivityReaderImpl.basePage={}", e.getMessage());
            return new Pagination<>(1, 20);
        }
    }

    @Override
    public ActivityCountQueryFeignVO activityCountQuery(ActivityCountQueryFeignDTO request) {
        Integer count = activityMapper.activityCountQuery(request);
        return ActivityCountQueryFeignVO.builder()
                .code(200)
                .res("正常")
                .count(count)
                .build();
    }

    /***
     * @Description:补充扩展信息 如我创建的 可参与 参与进度
     * @Author: zhangzy
     * @Date: 2021/6/28 17:10
     * @param list
     **/
    void fillScore(List<ActivityPageBO> list) {

        for (ActivityPageBO activityPageBO : list) {
            if (StringUtils.isBlank(activityPageBO.getRoleKey())) {
                activityPageBO.setRoleKey("notJoin");
                continue;
            }
            /**
             * 3.是否参与者 todo 与产品沟通,消耗过大,不返回具体参与度 该数据为无效数据
             * 如果我参加了.返回完成度
             */
            if (activityPageBO.getRoleKey().equals(RoleKeyEnum.MEMBER.getKey())) {
                // 参与度
                activityPageBO.setScore("20%");
                continue;
            }
        }

    }

    private void roleKey(List<ActivityPlanPageBO> list, Long userId) {
        if (!CollectionUtils.isEmpty(list) && Objects.nonNull(userId)) {
            List<Long> idList = list.stream().map(t -> Long.parseLong(t.getActivityId())).collect(Collectors.toList());
            List<ActivityUserDO> userList = activityUserDOMapper.findByActivityIdList(idList, userId);
            if (!CollectionUtils.isEmpty(userList)) {
                Map<Long, String> map = userList.stream().collect(Collectors.toMap(ActivityUserDO::getActivityId,
                        ActivityUserDO::getRoleKey, (key1, key2) -> key1));
                list.forEach(vo -> {
                    vo.setRoleKey(Objects.nonNull(map.get(Long.parseLong(vo.getActivityId())))
                            ? map.get(Long.parseLong(vo.getActivityId()))
                            : null);
                });
            }
        }
    }

    private void changeParameters(ActivityPageDTO dto) {
        if (Constant.ALL_STAGE_SUBJECT.equals(dto.getStageId())) {
            dto.setStageId(null);
        }
        if (Constant.ALL_STAGE_SUBJECT.equals(dto.getSubjectId())) {
            dto.setSubjectId(null);
        }
    }

    @Override
    public List<ActivityBO> selectActivityByDTO(ActivityCompletionUserFeignDTO build) {
        List<ActivityExpandDO> activityExpandDOS = ActivityExpandDOMapper.selectActivityByDTO(build);
        return activityConverter.convertExpandDOToBO(activityExpandDOS);
    }

    @Override
    public List<ActivityStageSubjectDTO> getActivityStageSubject(List<Long> activityIds) {
        if (CollectionUtils.isEmpty(activityIds)) {
            return new ArrayList<>();
        }
        List<ActivityExpandDO> activityExpandDOS = ActivityExpandDOMapper.selectActivityByActivityIds(activityIds);
        List<ActivityStageSubjectDTO> list = new ArrayList<>(activityExpandDOS.size());

        activityExpandDOS.forEach(e -> {
            ActivityStageSubjectDTO activityStageSubjectDTO = new ActivityStageSubjectDTO();
            activityStageSubjectDTO.setActivityId(e.getActivityId());
            // 学科学段
            List<ActivitySubjectStageDTO> subjectStage = JSON.parseArray(e.getSubjectStage(),
                    ActivitySubjectStageDTO.class);
            activityStageSubjectDTO.setSubjectStage(subjectStage);
            activityStageSubjectDTO.setGmtCreate(e.getGmtCreate());

            list.add(activityStageSubjectDTO);
        });
        return list;
    }

    @Override
    public Pagination<ZxjyAdminActivityPageBO> zxjyPage(ZxjyAdminActivityPageDTO dto) {
        Pagination<ZxjyAdminActivityPageBO> page = new Pagination<>(dto.getPageIndex(), dto.getPageSize());
        if (dto.getPlanId() != null) {
            List<Long> activityIds = nationalPlanFeignClient.getActivityIdsByTrainPlanId(dto.getPlanId());
            if (CollectionUtils.isEmpty(activityIds)) {
                page.setTotal(0);
                page.setRows(Lists.newArrayList());
                return page;
            }
            dto.setActivityIds(activityIds);
        }

        Integer count = activityMapper.countByZxjyPageDTO(dto);
        if (count < 1) {
            page.setTotal(0);
            page.setRows(Lists.newArrayList());
            return page;
        }
        log.info("***********查询入参service dto=" + JSON.toJSONString(dto));
        List<ZxjyAdminActivityPageDOEx> list = activityMapper.pageByZxjyPageDTO(dto);

        List<ZxjyAdminActivityPageBO> result = list.stream().map(e -> activityConverter.convertZxjyPageDoToBo(e))
                .collect(Collectors.toList());

        this.fillExpandContent(result);
        // 协作组名称 计划名称
        try {
            this.fillGroupName(result);
        } catch (Exception e) {
            log.error("调用协作组服务获取名称异常", e);
        }

        // 协作组名称 计划名称
        try {
            this.fillPlanName(result);
        } catch (Exception e) {
            log.error("调用教研计划服务获取名称异常", e);
        }

        page.setTotal(count);
        page.setRows(result);
        return page;
    }

    private void fillPlanName(List<ZxjyAdminActivityPageBO> result) {
        if (CollectionUtils.isEmpty(result)) {
            return;
        }
        List<Long> activityIds = result.stream().map(ZxjyAdminActivityPageBO::getId).collect(Collectors.toList());

        List<TrainPlanBO> list = nationalPlanFeignClient.getTrainPlanByActivityIds(activityIds);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, TrainPlanBO> map = new HashMap<>(activityIds.size());
            for (TrainPlanBO trainPlanBO : list) {
                if (!CollectionUtils.isEmpty(trainPlanBO.getActivityIds())) {
                    for (Long activityId : trainPlanBO.getActivityIds()) {
                        map.put(activityId, trainPlanBO);
                    }
                }
            }

            for (ZxjyAdminActivityPageBO zxjyAdminActivityPageBO : result) {
                TrainPlanBO trainPlanBO = map.get(zxjyAdminActivityPageBO.getId());
                if (trainPlanBO != null) {
                    zxjyAdminActivityPageBO.setPlanId(trainPlanBO.getId());
                    zxjyAdminActivityPageBO.setPlanName(trainPlanBO.getPlanName());
                }

            }
        }

    }

    private void fillGroupName(List<ZxjyAdminActivityPageBO> result) {
        if (CollectionUtils.isEmpty(result)) {
            return;
        }
        List<Long> groupIds = result.stream().map(ZxjyAdminActivityPageBO::getGroupId).collect(Collectors.toList());

        List<CoopGroupDTO> list = orgFeignClient.listAllByIds(groupIds);
        Map<Long, String> map = list.stream()
                .collect(Collectors.toMap(CoopGroupDTO::getId, CoopGroupDTO::getGroupName, (key1, key2) -> key1));

        for (ZxjyAdminActivityPageBO zxjyAdminActivityPageBO : result) {

            if (zxjyAdminActivityPageBO.getGroupId() != null) {
                zxjyAdminActivityPageBO.setGroupName(map.get(zxjyAdminActivityPageBO.getGroupId()));
            }
        }
    }

    @Override
    public List<ZxjyAdminActivityPageBO> getZxjyActivityListByActivityIds(String scene, List<Long> activityIds) {
        if (CollectionUtils.isEmpty(activityIds)) {
            return Lists.newArrayList();
        }
        List<ZxjyAdminActivityPageDOEx> list = activityMapper.listZxjyActivityBySceneAndIds(scene, activityIds);
        List<ZxjyAdminActivityPageBO> result = list.stream().map(e -> activityConverter.convertZxjyPageDoToBo(e))
                .collect(Collectors.toList());
        this.fillExpandContent(result);
        return result;
    }

    @Override
    public ActivityDO selectDOByActivityId(Long id) {

        return activityMapper.selectActivityById(id);
    }

    @Override
    public List<SchoolUserStatisticsFeignBO> statisticsBySchoolIdsAndBrand(SchoolUserStatisticsDTO dto) {
        if (CollectionUtils.isEmpty(dto.getSchoolIds()) || StringUtils.isBlank(dto.getDtBrand())) {
            return Lists.newArrayList();
        }

        List<SchoolUserStatisticsDOEx> list = activityMapper.statisticsBySchoolIdsAndBrand(dto);

        List<SchoolUserStatisticsFeignBO> result = new ArrayList<>();
        for (Long schoolId : dto.getSchoolIds()) {
            SchoolUserStatisticsFeignBO schoolUserStatisticsFeignBO = new SchoolUserStatisticsFeignBO();
            schoolUserStatisticsFeignBO.setSchoolId(schoolId);
            Integer total = list.stream().filter(e -> e.getSchoolId().equals(schoolId))
                    .map(SchoolUserStatisticsDOEx::getTotal).findFirst().orElse(0);
            schoolUserStatisticsFeignBO.setTotal(total);

            result.add(schoolUserStatisticsFeignBO);
        }

        return result;
    }

    @Override
    public ActivityResearchDictVO getActivityResearchDict(String scene) {
        ActivityResearchDictVO activityResearchDictVO = new ActivityResearchDictVO();

        /**
         * 教研主题
         */
        List<DictDTO> researchTheme = ActivityResearchThemeEnum.getAllDict();
        activityResearchDictVO.setResearchTheme(researchTheme);

        /**
         * 教研类型
         */
        List<DictDTO> researchType = ActivityResearchTypeEnum.getAllDict();
        activityResearchDictVO.setActivityResearchType(researchType);

        /**
         * 活动开展形式
         */
        List<DictDTO> activityType = ActivityJ02TypeEnum.getAllDict();
        activityResearchDictVO.setActivityType(activityType);

        return activityResearchDictVO;
    }

    @Override
    public void fillExpertList(Pagination<ZxjyAdminActivityPageBO> activityBOPagination) {
        if (activityBOPagination != null
                && !CollectionUtils.isEmpty(activityBOPagination.getRows())) {
            List<ZxjyAdminActivityPageBO> list = activityBOPagination.getRows();
            List<Long> activityIds = list.stream().map(ZxjyAdminActivityPageBO::getId).collect(Collectors.toList());
            List<ActivityPresenterBO> presenterList = activityPresenterReader.listByActivityIds(activityIds);

            for (ZxjyAdminActivityPageBO zxjyAdminActivityPageBO : list) {

                List<ActivityPresenterBO> activityPresenterBOS = presenterList.stream()
                        .filter(e -> e.getActivityId().equals(zxjyAdminActivityPageBO.getId()))
                        .collect(Collectors.toList());

                // 主备人
                List<ActivityPresenterBO> principals = activityPresenterBOS.stream()
                        .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                                && ActivityPresenterPersonTypeEnum.PRINCIPAL.getCode().equals(item.getPersonType()))
                        .collect(Collectors.toList());
                // 属性转换
                List<ActivityPrincipalDTO> principalDTOS = activityPresenterConverter
                        .convertToPrincipalDTOS(principals);
                zxjyAdminActivityPageBO.setActivityPrincipals(principalDTOS);
                // 授课教师
                List<ActivityPresenterBO> teachers = activityPresenterBOS.stream()
                        .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                                && ActivityPresenterPersonTypeEnum.TEACHER.getCode().equals(item.getPersonType()))
                        .collect(Collectors.toList());
                // 属性转换
                List<ActivityTeacherDTO> teacherDTOS = activityPresenterConverter.convertToTeacherDTOS(teachers);
                zxjyAdminActivityPageBO.setActivityTeachers(teacherDTOS);
                // 专家
                List<ActivityPresenterBO> experts = activityPresenterBOS.stream()
                        .filter(item -> StringUtils.isNotBlank(item.getPersonType())
                                && ActivityPresenterPersonTypeEnum.EXPERT.getCode().equals(item.getPersonType()))
                        .collect(Collectors.toList());
                // 属性转换
                List<ActivityExpertDTO> expertDTOS = activityPresenterConverter.convertToExpertDTOS(experts);
                zxjyAdminActivityPageBO.setActivityExperts(expertDTOS);
            }

        }

    }

    @Override
    public ActivityBO selectActivityBaseDetail(ActivityDetailDTO activityDetailDTO) {
        ActivityBO activityBO = this.getActivityBOFromRedis(activityDetailDTO);
        return activityBO;
    }

    private void fillExpandContent(List<ZxjyAdminActivityPageBO> result) {
        if (CollectionUtils.isEmpty(result)) {
            return;
        }
        List<Long> activityIds = result.stream().map(ZxjyAdminActivityPageBO::getId).collect(Collectors.toList());

        List<ActivityExpandContentBO> list = activityExpandContentReader
                .getActivityExpandContentByActivityIds(activityIds);
        Map<Long, List<ActivityExpandContentBO>> fileMap = list.stream()
                .collect(Collectors.groupingBy(ActivityExpandContentBO::getActivityId));

        for (ZxjyAdminActivityPageBO zxjyAdminActivityPageBO : result) {

            /**
             * 扩展内容集合
             */
            zxjyAdminActivityPageBO.setExpandContentList(fileMap.get(zxjyAdminActivityPageBO.getId()));

            /**
             * 教研主题
             */
            List<ActivityExpandContentBO> expandContentList = zxjyAdminActivityPageBO.getExpandContentList();
            String researchTheme = this.getResearchTheme(expandContentList);
            zxjyAdminActivityPageBO.setResearchTheme(researchTheme);
        }

    }

    private String getResearchTheme(List<ActivityExpandContentBO> expandContentList) {
        try {
            if (CollectionUtils.isEmpty(expandContentList)) {
                return "";
            }
            List<ActivityExpandContentBO> themeList = expandContentList.stream()
                    .filter(e -> e.getContentType().equals(ActivityExpandContentEnum.RESEARCH_THEME.getCode()))
                    .collect(Collectors.toList());

            StringBuilder stringResult = new StringBuilder();

            if (!org.apache.commons.collections4.CollectionUtils.isEmpty(themeList)) {
                for (int i = 0; i < themeList.size(); i++) {
                    // 如果是其他 且用户填写数据不为空 展示用户填写数据
                    if (ActivityResearchThemeEnum.getActivityType(themeList.get(i).getContentValue())
                            .equals(ActivityResearchThemeEnum.OTHER)
                            && StringUtils.isNotBlank(themeList.get(i).getDescription())) {

                        stringResult.append(themeList.get(i).getDescription());
                    } else {
                        stringResult.append(ActivityResearchThemeEnum
                                .getActivityType(themeList.get(i).getContentValue()).getName());
                    }
                    if (i != (themeList.size() - 1)) {
                        stringResult.append("、");
                    }
                }
            }
            return stringResult.toString();
        } catch (Exception e) {
            log.error("教研主题类型拼装失败", e);
            return "";
        }
    }

    @Override
    public List<ActivityStatisticsDTO> lastJoinListByQueryDTO(ActivityMyCountQueryDTO activityMyCountQueryDTO) {

        List<ActivityPageDO> list = activityMapper.lastJoinListByQueryDTO(activityMyCountQueryDTO);
        List<ActivityStatisticsDTO> result = list.stream().map(e -> activityConverter.convertPageDOToStatisticsDTO(e))
                .collect(Collectors.toList());
        return result;

    }

    @Override
    public void selectForUpdate() {
        activityMapper.selectForUpdate();
    }

    @Override
    public Map<Long, ActivityPageBO> mapActivityByToolIds(List<Long> ids) {
        List<ToolDO> toolDOList = toolReader.listByIds(ids);
        if (CollectionUtils.isEmpty(toolDOList)) {
            return Maps.newHashMap();
        }
        List<Long> activityIds = toolDOList.stream().map(e -> e.getActivityId()).collect(Collectors.toList());
        List<ActivityPageBO> list = this.listByActivityIds(activityIds);

        /**
         * toolId /activityId
         */
        Map<Long, Long> toolActivityIdMap = toolDOList.stream()
                .collect(Collectors.toMap(ToolDO::getId, ToolDO::getActivityId));

        /**
         * activityId / activityPageBO
         */
        Map<Long, ActivityPageBO> activityMap = list.stream()
                .collect(Collectors.toMap(ActivityPageBO::getId, Function.identity()));

        /**
         * toolId /activityPageBO
         */
        Map<Long, ActivityPageBO> resultMap = Maps.newHashMap();
        toolActivityIdMap.forEach((toolId, activityId) -> {
            ActivityPageBO activityBO = activityMap.get(activityId);
            if (activityBO != null) {
                resultMap.put(toolId, activityBO);
            }
        });
        return resultMap;
    }

    @Override
    public List<Long> listActivityByTemplateIdListAndState(List<Long> templateIdList, Integer state) {
        if (CollectionUtils.isEmpty(templateIdList)) {
            return Lists.newArrayList();
        }
        return activityMapper.listActivityByTemplateIdListAndState(templateIdList, state);
    }

    @Override
    public List<ActivityPageBO> listByActivityIdsAndUserId(List<Long> ids, Long userId) {
        List<ActivityPageDO> list = activityMapper.listByActivityIdsAndUserId(ids, userId);

        return activityConverter.convertPageDOToBOList(list);
    }

    @Override
    public ActivityCountAndLastResultDTO countAndLastByUser(ActivityMyCountQueryDTO activityMyCountQueryDTO) {
        return activityMapper.countAndLastByUser(activityMyCountQueryDTO);
    }
}
